package com.jsptpd.smartauth.modules.business.restcontrol;


import com.jsptpd.smartauth.common.util.AppAuthUtils;
import com.jsptpd.smartauth.common.util.HttpUtils;
import com.jsptpd.smartauth.common.util.StringUtil;
import com.jsptpd.smartauth.modules.business.model.Collector;
import com.jsptpd.smartauth.modules.business.model.Error;
import com.jsptpd.smartauth.modules.business.model.RespObj;
import com.jsptpd.smartauth.modules.business.service.ICollectorService;
import com.jsptpd.smartauth.modules.business.service.ILoginService;
import com.jsptpd.smartauth.modules.business.service.IUserService;
import com.jsptpd.smartauth.modules.business.utils.Constants;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.ModelAndView;

import java.io.IOException;
import java.util.Date;
import java.util.concurrent.ConcurrentHashMap;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;


/**
 * 统一登录管理
 */
@Controller
@RequestMapping("/")
public class LoginController {

    private static final int LOGIN_TYPE_ACCOUNT = 0;
    private static final int LOGIN_TYPE_TOKEN = 1;
    private static final int LOGIN_TYPE_WECHAT = 2;

    static ConcurrentHashMap<String, String> concurrentHashMap = new ConcurrentHashMap<>();


    @Scheduled(cron = "0 0 3 * * ?")
    public void clearTask() {
        concurrentHashMap.clear();
    }

    @Autowired
    ILoginService loginService;
    @Autowired
    IUserService userService;
    @Autowired
    ICollectorService collectorService;

    @Autowired
    private HttpServletResponse httpServletResponse;
    @Autowired
    private HttpServletRequest httpServletRequest;

    @Value("${config.url.loginWx}")
    String loginWxUrl;
    @Value("${config.bind.appId}")
    String bindAppId;
    @Value("${config.login.errState}")
    private String cfgLoginErrState;


    @ApiOperation(value="设备信息采集", notes="信息采集")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "userId", value = "用户名", required = true, dataType = "String",paramType = "query"),
    })
    @ResponseBody
    @RequestMapping(value = "/login/collect", method = RequestMethod.GET)
    public RespObj<String> collect(@RequestParam String userId) throws Exception {
        //信息采集
        collectorService.collect(HttpUtils.getCollectorHeader(httpServletRequest,userId,Constants.COLLECT_SIM_CPDAT));
        return new RespObj<String>(new Error(Constants.COMMON_ERRCODE_SUCC,null),"");
    }

    @ApiOperation(value="设备信息校验", notes="信息校验")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "userId", value = "用户名", required = true, dataType = "String",paramType = "query"),
    })
    @ResponseBody
    @RequestMapping(value = "/login/check", method = RequestMethod.GET)
    public RespObj<String> check(@RequestParam String userId) throws Exception {
        Collector collector = collectorService.selectOne(HttpUtils.getCollectorHeader(httpServletRequest,userId,Constants.COLLECT_SIM_CPDAT));
        if(collector!=null){
            Date lastTime = collector.getUpdateTime();
            Date currtime = new Date();
            if((currtime.getTime()-lastTime.getTime())<=1000*3600*12){
                return new RespObj<String>(new Error(Constants.COMMON_ERRCODE_SUCC,"已有设备信息"),"");
            }else{
                return new RespObj<String>(new Error(Constants.COMMON_ERRCODE_FAIL,"设备信息过期"),"");
            }
        }
        return new RespObj<String>(new Error(Constants.COMMON_ERRCODE_FAIL,"设备信息无效"),"");
    }

    /**
     * 原来cpdat的login接口，现在重定向到login/wxqr：绑定后扫码登录
     */
    @ApiOperation(value="微信回调cpdat的登录", notes="redirect，不必测")
    @RequestMapping(value = "login", method = RequestMethod.GET)
    public String login(@RequestParam String code, @RequestParam String state){
        return "redirect:"+String.format(loginWxUrl,code,state);
    }
    
    /**
     * login/wxqr：cpdat绑定后扫码登录
     */
    @ApiOperation(value="cpdat绑定后扫码登录", notes="cpdat绑定后扫码登录")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "code", value = "微信用户授权码", required = true, dataType = "String",paramType = "query"),
            @ApiImplicitParam(name = "state", value = "请求随机码", required = true, dataType = "String",paramType = "query")
    })
    @ResponseBody
    @RequestMapping(value = "login/wxqr", method = RequestMethod.GET)
    public ModelAndView loginWeChatQr(@RequestParam String code, @RequestParam String state) throws IOException {
        int resultCode = Constants.LOGIN_ERRCODE_STATE;
        String result = String.valueOf(resultCode);
        String resultTips = StringUtil.getValue(cfgLoginErrState,Constants.LOGIN_ERRMSG_STATE);

        RespObj<String> respData = loginService.loginWithWechat(code, state, bindAppId);

        if (respData!=null) {
            resultCode = respData.getError().getErrCode();
            result = String.valueOf(resultCode);
            if (resultCode==Constants.LOGIN_ERRCODE_SUCC) {
                result = respData.getData();
                //信息采集
                collectorService.collect(HttpUtils.getCollectorHeader(httpServletRequest,result,Constants.COLLECT_SIM_CPDAT));
            }
            resultTips = respData.getError().getErrMessage();
        }

        concurrentHashMap.put(state, result);

        ModelAndView view = new ModelAndView();
        view.setViewName("tips");
        view.addObject("result", resultTips);
        return view;
    }

    @ApiOperation(value="APP微信登录", notes="APP微信登录")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "code", value = "微信用户授权码", required = true, dataType = "String",paramType = "query"),
            @ApiImplicitParam(name = "state", value = "请求随机码", required = true, dataType = "String",paramType = "query")
    })
    @ResponseBody
    @RequestMapping(value = "login/wx", method = RequestMethod.GET)
    public RespObj<String> loginWeChat(@RequestParam String code, String state) throws Exception {
        return login(LOGIN_TYPE_WECHAT,code,state);
    }

    @ApiOperation(value="APP用户名密码登录", notes="APP登录",consumes="application/x-www-form-urlencoded")
    @ApiImplicitParams({
            @ApiImplicitParam(name="userId",value="用户名",required=true,dataType="String",paramType="body"),
            @ApiImplicitParam(name="password",value="密码",required=true,dataType="String",paramType="body")
    })
    @ResponseBody
    @RequestMapping(value = "login/account", method = RequestMethod.POST)
    public RespObj<String> loginAccount(@RequestParam String userId,@RequestParam String password) throws Exception {
        return login(LOGIN_TYPE_ACCOUNT,userId,password);
    }


    @ApiOperation(value="APP用token登录", notes="目前用http，后续会改成https，tokern在header里")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "userId", value = "用户名", required = true, dataType = "String",paramType = "query"),
    })
    @ResponseBody
    @RequestMapping(value = "/login/token", method = RequestMethod.GET)
    public RespObj<String> loginToken(@RequestParam String userId) throws Exception {
        String token = HttpUtils.getTokenInHeaders(httpServletRequest);
        return login(LOGIN_TYPE_TOKEN,userId,token);
    }

    /**
     * 登录通用方法：账号、token、微信
     */
    private RespObj<String> login(int loginType,String code,String token) throws Exception {
        Error error;
        RespObj<String> respData;
        String userId = code;

        //校验appId
        if(!AppAuthUtils.checkAppIdAndKey(httpServletRequest)){
            error = new Error(Constants.LOGIN_ERRCODE_STATE,StringUtil.getValue(cfgLoginErrState,Constants.LOGIN_ERRMSG_STATE));
            return new RespObj<String>(error,"");
        }
        String appId = AppAuthUtils.getAppId(httpServletRequest);

        if (loginType==LOGIN_TYPE_ACCOUNT) {
            respData = loginService.loginWithAccount(code,token);
        } else if (loginType==LOGIN_TYPE_TOKEN) {
            respData = loginService.loginWithToken(code,token);
        } else if (loginType==LOGIN_TYPE_WECHAT) {
            respData = loginService.loginWithWechat(code,token,appId);
        } else {
            error = new Error(Constants.LOGIN_ERRCODE_STATE,StringUtil.getValue(cfgLoginErrState,Constants.LOGIN_ERRMSG_STATE));
            return new RespObj<String>(error,"");
        }

        if (respData!=null && respData.getError().getErrCode()==Constants.LOGIN_ERRCODE_SUCC) {
            if(loginType==LOGIN_TYPE_ACCOUNT || loginType==LOGIN_TYPE_WECHAT){
                userId = respData.getData();
            }
            //信息采集
            collectorService.collect(HttpUtils.getCollectorHeader(httpServletRequest,userId,null));
            //发布token并设置响应头
            HttpUtils.setRespToken(appId, userId, httpServletResponse);
        }

        return respData;
    }

    @ApiOperation(value="cpdat绑定后扫码登录", notes="cpdat绑定后扫码登录")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "token", value = "请求随机码", required = true, dataType = "String"),
    })
    @ResponseBody
    @RequestMapping(value = "verify", method = RequestMethod.GET)
    public String verify(String token){
        String s = concurrentHashMap.get(token);
        if (s != null) {
            concurrentHashMap.remove(token);
        }
        return s;
    }


    @RequestMapping(value = "login/testUpload", method = RequestMethod.GET)
    public ModelAndView testUpload(@RequestParam String code) {

        ModelAndView view = new ModelAndView();
        view.setViewName("testUpload");
        view.addObject("code", code);
        return view;
    }
}